import { dialog, IpcMainEvent } from "electron"
import { load, loadAll } from "js-yaml"
import { readFile, readdir, writeFile, stat } from "node:fs/promises"
import * as types from '../types'

const re = {
    'img': /m_Sprite: {fileID: 2.*/,
    'spe': /---.*/g,
    'tag': /%TAG.*/,
}

async function handleFileOpen() {
    const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openDirectory', 'dontAddToRecent', 'noResolveAliases'] })
    if (!canceled) {
        return filePaths[0]
    } else return null
}

async function exists(path: string): Promise<boolean> {
    try {
        const stats = await stat(path);
        return stats.isDirectory()
    } catch (err) {
        return false
    }
}

export async function prefabInfo() {
    const path = await handleFileOpen()
    if (path == null) return
    let files = await readdir(path)
    files = files.filter((name) => {
        return name.endsWith('prefab')
    })
    if (files.length == 0) {
        let res: { 'pic': types.ItemInfoRet, 'spine': types.ItemInfoRet, 'scripts': types.ItemInfoRet, 'prefabs': types.PrefabRet } = {
            'pic': { dir: '', data: [] },
            'spine': { dir: '', data: [] },
            'scripts': { dir: '', data: [] },
            'prefabs': {},
        }
        if (await exists(path + '/Prefabs/Icons')) {
            res['prefabs'] = _dealPrefab(path + '/Prefabs/Icons', await readdir(path + '/Prefabs/Icons'))
        }
        if (await exists(path + '/Scripts/UI/Slot')) {
            res['scripts'] = await scriptInfo(path + '/Scripts/UI/Slot')
        } else if (await exists(path + '/Scripts/UI/Icon')) {
            res['scripts'] = await scriptInfo(path + '/Scripts/UI/Icon')
        }
        if (await exists(path + '/Spines')) {
            res['spine'] = await spineInfo(path + '/Spines')
        }
        for (const i of ['Image', 'Imgs', 'Textures']) {
            const p = `${path}/${i}/qz`
            if (await exists(p)) {
                res['pic'] = await picInfo(p)
                break
            }
        }
        return res
    } else {
        return _dealPrefab(path, files)
    }
}
function _dealPrefab(path: string, files: string[]) {
    files = files.filter((name) => {
        return name.endsWith('prefab')
    })
    let res: types.PrefabRet = {}
    for (const i of files) {
        res[i] = path + '/' + i
    }
    return res
}

export async function picInfo(v: string): Promise<types.ItemInfoRet>
export async function picInfo(v: undefined): Promise<types.ItemInfoRet | undefined>
export async function picInfo(v: string | undefined) {
    const path = (typeof v == 'string') ? v : await handleFileOpen()
    if (path == null) return
    let files = await readdir(path)
    files = files.filter((name) => {
        return name.endsWith('png.meta')
    })
    let res: types.ItemInfoRet = {
        'dir': path,
        'data': []
    }
    for (const i of files) {
        const data = await readFile(path + '/' + i, { encoding: 'utf-8' })
        const guid: any = load(data)
        res.data.push({ 'name': i.substring(0, i.length - 9), guid: guid['guid'] })
    }
    return res
}

export async function scriptInfo(v: string): Promise<types.ItemInfoRet>
export async function scriptInfo(v: undefined): Promise<types.ItemInfoRet | undefined>
export async function scriptInfo(v: string | undefined) {
    const path = (typeof v == 'string') ? v : await handleFileOpen()
    if (path == null) return
    let files = await readdir(path)
    files = files.filter((name) => {
        return name.endsWith('cs.meta')
    })
    let res: types.ItemInfoRet = {
        'dir': path,
        'data': []
    }
    for (const i of files) {
        const data = await readFile(path + '/' + i, { encoding: 'utf-8' })
        const guid: any = load(data)
        res.data.push({ 'name': i.substring(0, i.length - 8), guid: guid['guid'] })
    }
    return res
}

export async function spineInfo(v: string): Promise<types.ItemInfoRet>
export async function spineInfo(v: undefined): Promise<types.ItemInfoRet | undefined>
export async function spineInfo(v: string | undefined) {
    const path = (typeof v == 'string') ? v : await handleFileOpen()
    if (path == null) return
    let files = await readdir(path)
    files = files.filter((name) => {
        return name.endsWith('SkeletonData.asset.meta')
    })
    let res: types.ItemInfoRet = {
        'dir': path,
        'data': []
    }
    for (const i of files) {
        const data = await readFile(path + '/' + i, { encoding: 'utf-8' })
        const guid: any = load(data)
        res.data.push({ 'name': i.substring(0, i.length - 11), guid: guid['guid'] })
    }
    return res
}

export async function work(e: IpcMainEvent, data: types.WorkParam) {
    for (const i in data) {
        const file = await readFile(i, { encoding: 'utf-8' })
        const toParse = file.replace(re.spe, '---').replace(re.tag, '')
        const res = loadAll(toParse)
        const from: types.regData = {
            'spine': '',
            'img': '',
            'blurimg': '',
            'script': '',
        }
        const to = data[i]
        res.forEach((i: any) => {
            if ('MonoBehaviour' in i) {
                const data = i['MonoBehaviour']
                if (data['m_Script']['guid'] == 'd85b887af7e6c3f45a2e2d2920d641bc') {
                    //spine
                    from.spine = data['skeletonDataAsset']['guid']
                } else if ('m_staticImage' in data && from.script == '') {
                    from.img = data['m_staticImage']['guid']
                    from.blurimg = data['m_blurImage']['guid']
                    from.script = data['m_Script']['guid']
                }
            }
        })
        let ret = file.replace(re.img, 'm_Sprite: {fileID: 0}')
        let k: keyof types.regData
        for (k in from) {
            ret = ret.replace(from[k], to[k])
        }
        await writeFile(i, ret, { encoding: 'utf-8' })
    }
    dialog.showMessageBox({
        title: '操作成功！',
        message: '去unity继续搬砖吧。'
    })
}